//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "vector.h"

FC_NAMESPACE_BEGIN


// vector_ptr
//
// Implements a vector using void pointers internally.
// must only be used with pointer types.

template <class T, class Allocator>
class vector_ptr : public vector<void*, Allocator>
{
public:
	typedef T										value_type;
	typedef T*										pointer;
	typedef const T*								const_pointer;
	typedef T&										reference;
	typedef const T&								const_reference;
	typedef pointer									iterator;
	typedef const_pointer							const_iterator;
	typedef fc::reverse_iterator<iterator>			reverse_iterator;
	typedef fc::reverse_iterator<const_iterator>	const_reverse_iterator;
	typedef vector_ptr<T, Allocator>				this_type;
	typedef vector<void*, Allocator>				base_type;
	typedef typename base_type::allocator_type		allocator_type;

	using base_type::m_begin;
	using base_type::m_end;
	using base_type::m_capacity;
	using base_type::m_allocator;

	vector_ptr()
		: base_type()
		{
		}

	explicit vector_ptr( const allocator_type& alloc )
		: base_type(alloc)
		{
		}

	explicit vector_ptr( size_t n, const T& value = T(), const allocator_type& alloc = allocator_type() )
		: base_type(n, value, alloc)
		{
		}

	template<class InputIterator>
		vector_ptr( InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type() )
		: base_type(first, last, alloc)
		{
		}

	vector_ptr( const this_type& x )
		: base_type(x)
		{
		}

	reference operator [] ( size_t i ) { return *pointer(m_begin + i); }
	const_reference operator [] ( size_t i ) const { return *pointer(m_begin + i); }

	reference at( size_t i )
	{
		FC_ASSERT(i < size());
		return *pointer(m_begin + i);
	}

	const_reference at( size_t i ) const
	{
		FC_ASSERT(i < size());
		return *pointer(m_begin + i);
	}

	reference		front()			{ return (reference)*m_begin; }
	const_reference front() const	{ return (reference)*m_begin; }
	reference		back()			{ return (reference)*(m_end - 1); }
	const_reference back()	const	{ return (reference)*(m_end - 1); }
	iterator		begin()			{ return (iterator)m_begin; }
	const_iterator	begin() const	{ return (iterator)m_begin; }
	iterator		end()			{ return (iterator)m_end; }
	const_iterator	end() const		{ return (iterator)m_end; }
	const_iterator	cbegin() const	{ return (iterator)m_begin; }
	const_iterator	cend() const	{ return (iterator)m_end; }
	reverse_iterator		rbegin()		{ return reverse_iterator(end()); }
	const_reverse_iterator	rbegin() const	{ return const_reverse_iterator(end()); }
	reverse_iterator		rend()			{ return reverse_iterator(begin()); }
	const_reverse_iterator	rend() const	{ return const_reverse_iterator(begin()); }
	pointer data()				{ return begin(); }
	const_pointer data() const	{ return begin(); }

	iterator insert( iterator it, const T& value )
	{
		return (iterator)base_type::insert(it, value);
	}

	iterator erase( iterator it )
	{
		return (iterator)base_type::erase(it);
	}

	iterator erase( iterator first, iterator last )
	{
		return (iterator)base_type::erase(first, last);
	}

	iterator erase_unordered( iterator it )
	{
		return (iterator)base_type::erase_unordered(it);
	}

	pointer push_back_uninitialized( size_t n )
	{
		return (pointer)base_type::push_back_uninitialized(n);
	}

	this_type& operator =( const this_type& x )
	{
		base_type::operator =(x);
		return *this;
	}

};



FC_NAMESPACE_END
